using System;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.Project;
using Microsoft.WowAddonStudio.Project;
using Microsoft.WowAddonStudio.Project.Automation;

namespace Microsoft.WowAddonStudio.ProjectRefactor
{
	/// <summary>
	/// Creates implementation of IFrameXmlMerger based on arguments.
	/// </summary>
	public sealed class FrameXmlMergerFactory
	{
		public static readonly string BlizzardNamespace = "http://www.blizzard.com/wow/ui/";
		private readonly IServiceProvider serviceProvider;


		/// <summary>
		/// Initializes a new instance of the <see cref="FrameXmlMergerFactory"/> class.
		/// </summary>
		/// <param name="serviceProvider">The service provider.</param>
		public FrameXmlMergerFactory(IServiceProvider serviceProvider) : this(serviceProvider, null)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FrameXmlMergerFactory"/> class.
		/// </summary>
		/// <param name="merger">The merger.</param>
		public FrameXmlMergerFactory(IFrameXmlMerger merger)
			: this(null, merger)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FrameXmlMergerFactory"/> class.
		/// </summary>
		/// <param name="serviceProvider">The service provider.</param>
		/// <param name="merger">The merger.</param>
		public FrameXmlMergerFactory(IServiceProvider serviceProvider, IFrameXmlMerger merger)
		{
			if (serviceProvider == null)
				throw new ArgumentNullException("serviceProvider");

			Merger = merger;
			this.serviceProvider = serviceProvider;
		}

		/// <summary>
		/// Gets the merger.
		/// </summary>
		/// <value>The merger.</value>
		public IFrameXmlMerger Merger { get; private set; }

		/// <summary>
		/// Creates implementation of IFrameXmlMerger based on arguments.
		/// </summary>
		/// <param name="frameXmlPath">Path of FrameXml file.</param>
		/// <returns></returns>
		public IFrameXmlMerger CreateMerger(string frameXmlPath)
		{
			TextDocument document = GetTextDocumentForFrame(frameXmlPath);

			if (document == null)
				Merger = new FrameXmlFileMerger(frameXmlPath);
			else
				Merger = new FrameXmlDocumentMerger(frameXmlPath, document);

			return Merger;
		}

		/// <summary>
		/// Gets the text document for frame.
		/// </summary>
		/// <param name="frameXmlPath">The frame XML path.</param>
		/// <returns></returns>
		private TextDocument GetTextDocumentForFrame(string frameXmlPath)
		{
			if (serviceProvider != null)
			{
				var dte = serviceProvider.GetService(typeof (DTE)) as DTE;
				
				if (dte != null && dte.Documents != null)
				{
					var doc = dte.Documents.OfType<Document>().FirstOrDefault(
						document =>
							{
								if (document.ProjectItem is OAWowFileItem)
								{
									return document.ProjectItem.Properties.Item("FullPath").Value.ToString() ==
									       frameXmlPath;
								}
								return false;
							}
						);

					if (doc != null)
						return (TextDocument) doc.Object("TextDocument");
				}
			}
			return null;
		}

		/// <summary>
		/// Determines whether [is frame XML file] [the specified file].
		/// </summary>
		/// <param name="file">The file.</param>
		/// <returns>
		/// 	<c>true</c> if [is frame XML file] [the specified file]; otherwise, <c>false</c>.
		/// </returns>
		private static bool IsFrameXmlFile(HierarchyNode file)
		{
			return file.ItemNode.GetMetadata(ProjectFileConstants.SubType) == WowSubType.Frame;
		}
	}
}